package cn.wgx.modules.base.web;

import cn.wgx.commons.util.EMailUtil;
import cn.wgx.commons.util.StringUtils;
import cn.wgx.commons.util.ValidateCodeImageUtil;
import cn.wgx.commons.util.Validation;
import cn.wgx.modules.sys.entity.SysUser;
import cn.wgx.modules.sys.services.SysUserService;
import cn.wgx.modules.sys.util.UserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Api(description = "邮件接口")
@RestController
@RequestMapping(value = "api/email")
public class EMailController extends BaseController {

    @Resource
    SysUserService sysUserService;

    private Map<String, Date> sendMailDateMap;
//QQ注册:2172625685 //2020.3.11 14天后可用
    public final static String SESSION_BIND_KEY_DATE = "emailsenddate";
    public final static String SESSION_BIND_KEY_EMAIL = "bindemailkey";
    public final static String SESSION_BIND_SEND_EMAIL = "sendemail";
    public final static String VCODE_TYPE = "SESSION_BIND_IS_SMS";

    private final static String EMAIL_STRING_BIND = "您正在注册，验证码为：{{code}}，有效期十分钟，请勿泄漏验证码。如非本人操作，请联系我们010-64128837。";
    private final static String EMAIL_STRING_CHANGE_PASS = "您正在设置登录密码，验证码为：{{code}}，有效期十分钟，请勿泄漏验证码，唯一热线010-64128837。";
    private final static String EMAIL_STRING_CHANGE_EMAIL = "您正在设置新的邮件地址，验证码为：{{code}}，有效期十分钟，请勿泄漏验证码，唯一热线010-64128837。";

    @ApiOperation("注册帐号,发送邮箱验证码")
    @RequestMapping(value = "bind", method = RequestMethod.GET)
    public Map<String,Object> sendSMS(@RequestParam String email,
                                      HttpSession session){
        Map<String,Object> map = getInitMap();
        if(!checkCanSend(email, session, map)){
            return map;
        }else if(!sysUserService.checkPEmail(email)){
            return  returnErrorMap("此邮箱已注册", map);
        }else{
            return sendEmailByType(email,1,session);
        }
    }

    @ApiOperation("找回密码发送验证码,需要邮箱地址")
    @RequestMapping(value = "changepass", method = RequestMethod.GET)
    public Map<String,Object> changePassSMS(@RequestParam String email,
                                            HttpSession session){
        Map<String,Object> map = getInitMap();
        if(!checkCanSend(email, session, map)){
            return map;
        }
        SysUser sysUser = sysUserService.getSysUserByEmail(email, false);
        if(null != sysUser){
            return sendEmailByType(email, 2, session);
        }else{
            returnErrorMap("未知邮箱用户.",map);
        }
        return map;
    }


    @ApiOperation("修改 - 旧邮箱发送验证码")
    @RequiresRoles("user")
    @RequestMapping(value = "validemail", method = RequestMethod.GET)
    public Map<String,Object> validOldEmail(HttpSession session){
        SysUser sysUser = UserUtil.getUser();
        String email = sysUser.getEmail();
        Map<String,Object> map = getInitMap();
        if(!sysUser.getEmailCheck()){
            return returnErrorMap(email.substring(0,2)+ "**@**." + StringUtils.getFileExt(email) +",用户邮箱未验证.", map);
        }
        if(!checkCanSend(email, session, map)){
            return map;
        }
        return sendEmailByType(email, 3, session);
    }


    @ApiOperation("修改 - 验新邮箱发送验证码,需要提交旧邮箱证码")
    @RequiresRoles("user")
    @RequestMapping(value = "changeemail/{code}", method = RequestMethod.GET)
    public Map<String,Object> changeEmailCode(@PathVariable("code") String code,
                                              @RequestParam String email,
                                              HttpSession session){
        Map<String,Object> map = getInitMap();
        if(!ValidateCodeImageUtil.validCode(session,code,map,true)){
            return returnErrorMap("验证码错误",map);
        }else if(!sysUserService.checkPEmail(email)){
            return  returnErrorMap("此邮箱已注册", map);
        }
//        if(!checkCanSend(email, session, map)){
//            return map;
//        }
        return sendEmailByType(email, 3, session);
    }


    /**
     * 检测验证码正确
     * @param code
     * @param session
     * @return
     */
    @ApiOperation("检测邮箱验证码是否正确")
    @RequestMapping(value = "checkcode/{code}", method = RequestMethod.GET)
    public Map<String,Object> checkCode(@PathVariable String code,HttpSession session){

        Map<String,Object> map = getInitMap();
        if(!ValidateCodeImageUtil.validCode(session,code,map,false)){
            return returnErrorMap("验证码错误",map);
        }
        return map;

    }


    /**
     * 发送邮件
     * @param email
     * @param type
     * @param session
     * @return
     */
    private Map<String,Object> sendEmailByType(String email,
                                      Integer type,
                                      HttpSession session){
        Map<String,Object> map = getInitMap();
//        if(!checkCanSend(email, session, map)){
//            return map;
//        }
        String code = StringUtils.getRadomCode();
        String message;
        String title ;
        if(type == 1){
            message = EMAIL_STRING_BIND.replace("{{code}}",code);
            title = "中科北影-注册验证码";
        }else if(type == 2){
            message = EMAIL_STRING_CHANGE_PASS.replace("{{code}}",code);
            title = "中科北影-改密验证码";
        }else if(3 == type){
            message = EMAIL_STRING_CHANGE_EMAIL.replace("{{code}}",code);
            title = "中科北影-更改邮箱验证码";
        }else{
            return returnErrorMap("",map);
        }
        boolean b = EMailUtil.sendSimpleEMail(email,title,message);
        if(b){
            Date d = new Date();
            session.setAttribute(SESSION_BIND_KEY_EMAIL, code);
            session.setAttribute(SESSION_BIND_KEY_DATE, d );
            session.setAttribute(SESSION_BIND_SEND_EMAIL, email);
//            session.setAttribute(SMSController.SESSION_BIND_IS_SMS, false);
            session.setAttribute(VCODE_TYPE, "email");
            saveSendEmail(email, new Date());
        }else{
            return returnErrorMap("邮件发送失败",map);
        }
        returnData(b, map);
        return map;
    }



    private boolean checkCanSend(String email, HttpSession session, Map<String,Object> map){
        if(!Validation.isEmail(email)){
            returnErrorMap("邮箱格式不正确",map);
            return false;
        }
        if(!checkSendEmailTimeless(session)){
            returnErrorMap("发送时间间隔过短(1分钟).",map);
            return false;
        }
        return true;
    }

    /**
     * 检测短信发送时间间隔,大于1分钟返回true
     * @param session
     * @return
     */
    public boolean checkSendEmailTimeless(HttpSession session){
        Object o = session.getAttribute(SESSION_BIND_KEY_DATE);
        if(o != null && o instanceof Date){
            Date d = (Date)o;
            long old = d.getTime();
            return (new Date().getTime() - old) > (1000*60) && checkMap(session.getAttribute(SESSION_BIND_SEND_EMAIL)!=null?session.getAttribute(SESSION_BIND_SEND_EMAIL).toString():null);
        }
        return true;
    }

    private void saveSendEmail(String email, Date date){
        if(sendMailDateMap == null){
            sendMailDateMap = new ConcurrentHashMap<String, Date>();
        }
        if(date == null) date = new Date();
        sendMailDateMap.put(email, date);
    }

    private boolean checkMap(String email){
        if(sendMailDateMap == null){
            return true;
        }
        Iterator<Map.Entry<String,Date>> iterator = sendMailDateMap.entrySet().iterator();
        Date nowdate = new Date();
        while(iterator.hasNext()){
            Map.Entry<String,Date> entry = iterator.next();
            Date d = entry.getValue();
            if(nowdate.getTime() - d.getTime() > (60*1000)){
                sendMailDateMap.remove(entry.getKey());
            }
        }
        if(sendMailDateMap.containsKey(email)){
            Date d = sendMailDateMap.get(email);
            if(nowdate.getTime() - d.getTime() < (60*1000)){
                return false;
            }
        }
        return true;
    }

    public static void main(String a[]){
       System.out.println(StringUtils.getRadomCode());
    }
}
